package com.ruoyi.common.utils.embedding;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.config.AiBaseInfoConfig;
import com.ruoyi.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.ai.embedding.EmbeddingModel;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 阿里云百炼文本向量化服务
 */
@Slf4j
public class EmbeddingUtils {


    /**
     * 多模态向量
     *
     * @param segmentContent 文本 视频 图片
     * @param type           类型 text image video
     * @return 向量
     */
    public static List<Float> createMultimodalEmbeddings(String segmentContent, String type) {


        JSONObject jsonObject1 = new JSONObject();
        jsonObject1.put(type, segmentContent);
        JSONArray objects = new JSONArray();
        objects.add(jsonObject1);

        JSONObject content = new JSONObject();
        content.put("contents", objects);

        JSONObject input = new JSONObject();
        input.put("model", "multimodal-embedding-v1");
        input.put("input", content);
        // 使用 Hutool 发送 POST 请求
        try (cn.hutool.http.HttpResponse accept = cn.hutool.http.HttpRequest.post("https://dashscope.aliyuncs.com/api/v1/services/embeddings/multimodal-embedding/multimodal-embedding").header("Content-Type", "application/json").header("Authorization", "Bearer " + AiBaseInfoConfig.getKey()).body(input.toJSONString()).execute()) {
            String res = accept.body();
            JSONObject jsonObject = JSON.parseObject(res, JSONObject.class);
            JSONObject data = jsonObject.getJSONObject("output");
            JSONArray embeddings1 = data.getJSONArray("embeddings").getJSONObject(0).getJSONArray("embedding");

            List<Float> embeddings2 = embeddings1.toJavaList(Float.class);
            if (CollectionUtil.isEmpty(embeddings2)) {
                throw new RuntimeException("获取文本向量失败: " + res);
            }
            System.out.println(embeddings2);
            return embeddings2;
        }
    }


    /**
     * 获取文本向量
     */
    public static List<Float> createEmbeddings(String text) {
        try {
            HttpClient client = HttpClient.newHttpClient();

            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();

            HttpRequest request;

            // 根据连接类型判断并构建HTTP请求
            // connectType 分为 local（本地） 和  network （网络）
            if (AiBaseInfoConfig.getConnectType().equals("local")) {
                String model = "Qwen3-Embedding-8B";
                String model2 = "text-embedding-v3";
                if (model.equals(AiBaseInfoConfig.getEmbeddingModel())) {

                    requestBody.put("model", model);
                    requestBody.put("input", text);
                    // 日志输出
                    log.debug("Request Url: {}, Request Body: {}, Request Input: {}", AiBaseInfoConfig.getEmbeddingUrl(), requestBody, text);
                    // 使用 Hutool 发送 POST 请求
                    try (cn.hutool.http.HttpResponse accept = cn.hutool.http.HttpRequest.post(AiBaseInfoConfig.getEmbeddingUrl()).header("Content-Type", "application/json").header("accept", "application/json").body(JSON.toJSONString(requestBody)).execute()) {
                        String res = accept.body();
                        JSONObject jsonObject = JSON.parseObject(res, JSONObject.class);
                        JSONArray data = jsonObject.getJSONArray("data");
                        JSONArray embeddings1 = data.getJSONObject(0).getJSONArray("embedding");

                        List<Float> embeddings2 = embeddings1.toJavaList(Float.class);
                        if (CollectionUtil.isEmpty(embeddings2)) {
                            throw new RuntimeException("获取文本向量失败: " + res);
                        }
                        return embeddings2;
                    }

                } else if (model2.equals(AiBaseInfoConfig.getEmbeddingModel())) {
                    List<String> inputs = new ArrayList<>();
                    inputs.add("\"" + text + "\"");
                    requestBody.put("inputs", inputs.toString());
                    // 日志输出
                    log.debug("Request Url: {}, Request Body: {}, Request Input: {}", AiBaseInfoConfig.getEmbeddingUrl(), requestBody, inputs);

                    request = HttpRequest.newBuilder().uri(URI.create(AiBaseInfoConfig.getEmbeddingUrl())).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(JSON.toJSONString(requestBody))).build();

                    // 发送请求
                    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

                    if (response.statusCode() == 200) {
                        // 解析响应
                        JSONArray jsonArray = JSONArray.parseArray(response.body());
                        return JSONArray.parseArray(jsonArray.get(0).toString()).toJavaList(Float.class);
                    } else {
                        log.error("Failed to get embeddings: {}", response.body());
                        throw new RuntimeException("获取文本向量失败: " + response.body());
                    }
                } else {
                    List<String> inputs = new ArrayList<>();
                    inputs.add("\"" + text + "\"");
                    requestBody.put("inputs", inputs.toString());
                    // 日志输出
                    log.debug("Request Url: {}, Request Body: {}, Request Input: {}", AiBaseInfoConfig.getEmbeddingUrl(), requestBody, inputs);

                    request = HttpRequest.newBuilder().uri(URI.create(AiBaseInfoConfig.getEmbeddingUrl())).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(JSON.toJSONString(requestBody))).build();

                    // 发送请求
                    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

                    if (response.statusCode() == 200) {
                        // 解析响应
                        JSONArray jsonArray = JSONArray.parseArray(response.body());
                        return JSONArray.parseArray(jsonArray.get(0).toString()).toJavaList(Float.class);
                    } else {
                        log.error("Failed to get embeddings: {}", response.body());
                        throw new RuntimeException("获取文本向量失败: " + response.body());
                    }
                }

            } else {

                // 构建HTTP请求
                requestBody.put("model", AiBaseInfoConfig.getEmbeddingModel());
                Map<String, Object> parameters = new HashMap<>();
                // text-embedding-v3的向量维度为1024
                parameters.put("dimension", 1024);
                requestBody.put("parameters", parameters);
                Map<String, Object> input = new HashMap<>();
                input.put("texts", List.of(text));
                requestBody.put("input", input);
                request = HttpRequest.newBuilder().uri(URI.create(AiBaseInfoConfig.getEmbeddingUrl())).header("Authorization", "Bearer " + AiBaseInfoConfig.getKey()).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(JSON.toJSONString(requestBody))).build();

                // 发送请求
                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

                if (response.statusCode() == 200) {
                    // 解析响应
                    JSONObject result = JSON.parseObject(response.body());

                    return result.getJSONObject("output").getJSONArray("embeddings").getJSONObject(0).getJSONArray("embedding").toJavaList(Float.class);
                } else {
                    log.error("Failed to get embeddings: {}", response.body());
                    throw new RuntimeException("获取文本向量失败: " + response.body());
                }
            }

        } catch (Exception e) {
            log.error("Failed to create embeddings: {} {}", text, e.getMessage());
            throw new RuntimeException(text + "创建文本向量失败", e);
        }
    }

    /**
     * 获取文本稀疏向量
     */
    /**
     * 获取文本稀疏向量
     */
    public static List<Map<Long, Float>> createSparseEmbeddings(String text) {
        try {
            HttpClient client = HttpClient.newHttpClient();


            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", AiBaseInfoConfig.getEmbeddingModel());

            Map<String, Object> input = new HashMap<>();
            input.put("texts", List.of(text));
            requestBody.put("input", input);

            Map<String, Object> parameters = new HashMap<>();
            // 指定输出类型为稀疏向量
            parameters.put("output_type", "sparse");
            requestBody.put("parameters", parameters);

            log.info("Request Url: {}, Request Body: {}", AiBaseInfoConfig.getEmbeddingUrl(), requestBody);
            // 构建HTTP请求
            HttpRequest request = HttpRequest.newBuilder().uri(URI.create(AiBaseInfoConfig.getEmbeddingUrl())).header("Authorization", "Bearer " + AiBaseInfoConfig.getKey()).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString(JSON.toJSONString(requestBody))).build();

            // 发送请求
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

            if (response.statusCode() == 200) {
                // 解析响应
                JSONObject result = JSON.parseObject(response.body());
                List<Map<Long, Float>> sparseEmbeddings = result.getJSONObject("output").getJSONArray("embeddings").toJavaList(JSONObject.class).stream().map(json -> {
                    log.info("{}", json);
                    return json.getJSONArray("sparse_embedding").toJavaList(JSONObject.class).stream().collect(Collectors.toMap(j -> j.getLongValue("index"), j -> j.getFloatValue("value")));
                }).collect(Collectors.toList());

                return sparseEmbeddings;
            } else {
                log.error("Failed to get embeddings: {}", response.body());
                throw new RuntimeException("获取文本向量失败: " + response.body());
            }

        } catch (Exception e) {
            log.error("Failed to create embeddings: {}", e.getMessage());
            throw new RuntimeException("创建文本向量失败", e);
        }
    }
}
